import { StoreModuleData } from '../modules/TypeConstraints';
import React from 'react';
import produce from 'immer';
import { getModuleDataById, isContainer } from '../utils/utils';

export interface StoreState {
  moduleDataListMap: Record<StoreModuleData['id'], StoreModuleData>;
  selectModuleDataIds: Array<StoreModuleData['id']>;
  moduleDataList: StoreModuleData[];
}

export enum StoreActionType {
  // 批量添加组件
  AddModuleDataList = 'addModuleDataList',
  // 批量删除组件
  DeleteModuleDataList = 'deleteModuleDataList',
  // 批量更新组件
  UpdateModuleDataList = 'updateModuleDataList',
  // 批量更新 select id
  UpdateSelectModuleDataIds = 'updateSelectModuleDataIds',
  // 往容器中添加元素
  AddChildrenByContainerId = 'AddChildrenByContainerId',
}

export interface StoreAction {
  type: StoreActionType;
  payload: any;
}

export type StoreDispatch = React.Dispatch<StoreAction>;

// 创建初始化的 store
export function createInitialStore(): StoreState {
  return {
    selectModuleDataIds: [],
    moduleDataListMap: {},
    moduleDataList: [],
  };
}

// reducer
export const reducer = produce(function (
  prevState: StoreState,
  action: StoreAction,
) {
  const { payload, type } = action;
  const { moduleDataList, selectModuleDataIds } = prevState;
  switch (type) {
    /* 批量添加组件 */
    case StoreActionType.AddModuleDataList: {
      // resetSelection 是否重置选择元素
      const {
        moduleDataList: toAddModuleDataList,
        resetSelection = false,
        parentId,
      } = payload as {
        moduleDataList: StoreModuleData[];
        resetSelection?: boolean;
        parentId?: StoreModuleData['id'];
      };

      let beToAddArr: StoreModuleData[] = [];
      if (!parentId) {
        // 向顶级添加子元素
        beToAddArr = moduleDataList;
      } else {
        // 找到父亲元素
        const parentInfo = getModuleDataById(parentId, moduleDataList);
        if (!parentInfo) throw '选择元素不存在';
        const { node: moduleData } = parentInfo;
        if (!isContainer(moduleData)) throw '选择元素不是容器';
        // 初始化
        if (!moduleData.props.children) {
          moduleData.props.children = [];
        }
        beToAddArr = moduleData.props.children;
      }
      toAddModuleDataList.forEach((moduleData) => {
        beToAddArr.push(moduleData);
      });
      // 更新选择元素
      if (resetSelection) {
        prevState.selectModuleDataIds = toAddModuleDataList.map(
          (moduleData) => moduleData.id,
        );
      }
      return;
    }
    /* 批量删除组件 */
    case StoreActionType.DeleteModuleDataList: {
      const { moduleDataIds: toDeleteModuleDataIds } = payload as {
        moduleDataIds: StoreModuleData['id'][];
      };
      toDeleteModuleDataIds.forEach((moduleDataId) => {
        const nodeInfo = getModuleDataById(moduleDataId, moduleDataList);
        if (!nodeInfo) throw '删除元素不存在';
        const { parent } = nodeInfo;
        let nodeContainerList =
          parent && isContainer(parent)
            ? parent.props.children || []
            : moduleDataList;
        const nodeIndex = nodeContainerList?.findIndex(
          (node) => node.id === moduleDataId,
        );
        nodeContainerList?.splice(nodeIndex, 1);
      });
      // 更新选择元素数组
      prevState.selectModuleDataIds = selectModuleDataIds.filter(
        (id) => !toDeleteModuleDataIds.includes(id),
      );
      return;
    }
    /* 批量更新组件 */
    case StoreActionType.UpdateModuleDataList: {
      const { moduleDataList: toUpdateModuleDataList, merge: isMerge = false } =
        payload as {
          moduleDataList: StoreModuleData[];
          merge?: boolean;
        };
      toUpdateModuleDataList.forEach((toUpdateModuleData) => {
        const { id } = toUpdateModuleData;
        const nodeInfo = getModuleDataById(id, moduleDataList);
        if (!nodeInfo) throw '更新元素不存在';
        const { node } = nodeInfo;
        if (isMerge) {
          node.props = Object.assign({}, node.props, toUpdateModuleData.props);
        } else {
          node.props = toUpdateModuleData as any;
        }
      });
      return;
    }
    /* 批量更新激活组件：比如多选 */
    case StoreActionType.UpdateSelectModuleDataIds: {
      const {
        selectModuleDataIds: toUpdateSelectModuleDataIds,
        isReset = false,
      } = payload as {
        selectModuleDataIds: Array<StoreModuleData['id']>;
        isReset?: boolean;
      };

      let newSelectModuleDataIds = [];
      if (isReset) {
        newSelectModuleDataIds = [...toUpdateSelectModuleDataIds];
      } else {
        newSelectModuleDataIds = [
          ...selectModuleDataIds,
          ...toUpdateSelectModuleDataIds,
        ];
      }
      prevState.selectModuleDataIds = newSelectModuleDataIds;
      return;
    }
    default:
      return createInitialStore();
  }
});

// 创建 context
export function createContext<T>(initialContext: T, displayName: string) {
  const context = React.createContext<T>(initialContext); //  这里可以省略
  context.displayName = displayName;
  return context;
}
